﻿/*
 * (c) Stefan Bojarovski 2010
 * */
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ASTBuilder
{
    class AssignmentNode : NodesCollection, ITreeNode
    {
        private LexemeType lexType = LexemeType.ASSIGNMENT;
        private IdentifierNode Identifier;
        private ITreeNode Expression;
        

        public AssignmentNode(IdentifierNode someId, ITreeNode Expr)
        {
            Identifier = someId;
            Expression = Expr;
        }

        public LexemeType getLexemeType()
        {
            return lexType;
        }
        public void printNode(String parentLevel, StreamWriter someStream)
        {
            someStream.WriteLine(parentLevel + " " + "Assign: " + Identifier.getName() + " = ");
            Expression.printNode(parentLevel + " ", someStream);
        }
        public List<Command> evalNode(ref Direction next, 
                                        ref Dictionary<String, Pair<IdentifierType, object>> Environment)
        {
            List<Command> assign = new List<Command>();
            if (next != Direction.JUMP)
            {
                String idName = Identifier.getName();
                Command evalExpr = Expression.evalNode(ref next, ref Environment)[0];

                if (Environment.ContainsKey(idName))
                {
                    switch (Environment[idName].getLeft())
                    {
                        case IdentifierType.BOOL:
                            if (evalExpr.getIdValue() is bool)
                            {
                                Environment[idName].setRight(evalExpr.getIdValue());
                                assign.Add(new Command(CommandType.ENVIRONMENTMODIFICATION, idName, 
                                                                                evalExpr.getIdValue()));
                            }
                            else
                            {
                                assign.Add(new Command(CommandType.ERRORUNCOMPATIBLETYPES, idName, 
                                                                                evalExpr.getIdValue()));
                            }
                            break;
                        case IdentifierType.INT:
                            if (evalExpr.getIdValue() is int)
                            {
                                Environment[idName].setRight(evalExpr.getIdValue());
                                assign.Add(new Command(CommandType.ENVIRONMENTMODIFICATION, idName, 
                                                                                evalExpr.getIdValue()));
                            }
                            else
                            {
                                assign.Add(new Command(CommandType.ERRORUNCOMPATIBLETYPES, idName, 
                                                                                evalExpr.getIdValue()));
                            }
                            break;
                        /*case IdentifierType.FUNCTION:
                            Pair<IArithmeticNode, IArithmeticNode> fBody = 
                                new Pair<IArithmeticNode,IArithmeticNode>(null,null);
                            if (Expression.getLexemeType() == LexemeType.BOOL_EXPRESSION)
                            {
                                IArithmeticNode funExpr = (IArithmeticNode)Expression;
                                fBody = new Pair<IArithmeticNode, IArithmeticNode>
                                                (funExpr.getFirst(), funExpr.getSecond());
                                Environment[idName].setRight(fBody);
                                assign.Add(new Command(CommandType.ENVIRONMENTMODIFICATION, idName, fBody));
                            }
                            else
                            {
                                assign.Add(new Command(CommandType.ERRORUNCOMPATIBLETYPES, idName, fBody));
                            }
                            break;*/
                        case IdentifierType.UNKNOWN:
                            assign.Add(new Command(CommandType.ERRORUNDECLAREDID, idName, null));
                            break;
                        default:
                            assign.Add(new Command(CommandType.ERRORUNCOMPATIBLETYPES, idName, evalExpr.getIdValue()));
                            break;
                    }
                }
                else
                {
                    assign.Add(new Command(CommandType.ERRORNOSUCHID, idName, null));
                }
                return assign;
            }
            else
            {
                assign.Add(new Command(CommandType.VOID, null, null));
                return assign;
            }
        }
    }
}
